import sys
import serial
import serial.tools.list_ports
from PySide6.QtCore import Qt, Slot, QEvent
from PySide6.QtWidgets import QApplication, QWidget
from ui_gnss import Ui_gnss
import threading


class MyWidget(QWidget):
    def __init__(self):
        super(MyWidget, self).__init__()
        self.ui = Ui_gnss()
        self.ui.setupUi(self)

        # 信号与槽
        self.ui.btn_open_com.clicked.connect(self.open_serial)
        # self.ui.combo_com_port.currentIndexChanged.connect(self.change_serial_port)
        # self.ui.combo_com_baud_rate.currentIndexChanged.connect(
        #     self.change_serial_port)
        # self.ui.combo_com_parity.currentIndexChanged.connect(
        #     self.change_serial_port)
        # self.ui.combo_com_data_bits.currentIndexChanged.connect(
        #     self.change_serial_port)
        # self.ui.combo_com_flow_control.currentIndexChanged.connect(
        #     self.change_serial_port)
        self.ui.btn_cloud_rd.clicked.connect(self.read_cloud)
        self.ui.btn_cloud_wr.clicked.connect(self.write_cloud)
        self.ui.btn_dev_id_rd.clicked.connect(self.read_dev_id)
        self.ui.btn_dev_id_wr.clicked.connect(self.write_dev_id)
        self.ui.btn_radar_rd.clicked.connect(self.read_radar)
        self.ui.btn_radar_wr.clicked.connect(self.write_radar)
        self.ui.btn_rtd_rd.clicked.connect(self.read_rtd)
        self.ui.btn_rtd_wr.clicked.connect(self.write_rtd)
        self.ui.btn_agnss_rd.clicked.connect(self.read_agnss)
        self.ui.btn_agnss_wr.clicked.connect(self.write_agnss)
        self.ui.btn_run_rd.clicked.connect(self.read_run_time)
        self.ui.btn_run_wr.clicked.connect(self.write_run_time)
        self.ui.btn_wakeup_rd.clicked.connect(self.read_wakeup)
        self.ui.btn_wakeup_wr.clicked.connect(self.write_wakeup)
        self.ui.btn_volume_rd.clicked.connect(self.read_volume)
        self.ui.btn_volume_wr.clicked.connect(self.write_volume)
        self.ui.btn_clear.clicked.connect(self.ui.text_edit_display.clear)

        # 设置默认参数
        # 获取可用串口列表
        self.rx_bytes = bytes()
        self.my_serial = serial.Serial()
        self.serial_list_info = serial.tools.list_ports.comports()
        if len(self.serial_list_info) == 0:
            print('no serial.')
        else:
            for i in range(0, len(self.serial_list_info)):
                self.ui.combo_com_port.addItem(
                    f"{self.serial_list_info[i].name} - {self.serial_list_info[i].description}"
                )

        self.ui.combo_com_baud_rate.setCurrentText('9600')
        self.ui.combo_com_data_bits.setCurrentText('8')
        self.ui.combo_com_parity.setCurrentText('none')
        self.ui.combo_com_flow_control.setCurrentText('none')

    def closeEvent(self, event):
        # 应用关闭后，关闭串口
        if self.my_serial.is_open:
            self.my_serial.close()

    @Slot()
    def open_serial(self):
        # 打开串口
        if self.my_serial.is_open:
            # 关闭串口
            self.my_serial.close()
            self.ui.btn_open_com.setText('打开串口')
            self.ui.combo_com_baud_rate.setEditable(False)
            self.ui.combo_com_data_bits.setEditable(False)
            self.ui.combo_com_flow_control.setEditable(False)
            self.ui.combo_com_parity.setEditable(False)
            self.ui.combo_com_stop_bits.setEditable(False)
            self.ui.combo_com_port.setEditable(False)
        else:
            # 串口
            port_index = self.ui.combo_com_port.currentIndex()
            # 波特率
            baud_rate = self.ui.combo_com_baud_rate.currentText()
            # 数据位
            data_bits = self.ui.combo_com_data_bits.currentText()
            # 检验位
            if self.ui.combo_com_parity.currentText() == 'none':
                parity = serial.PARITY_NONE
            elif self.ui.combo_com_parity.currentText() == 'odd':
                parity = serial.PARITY_ODD
            elif self.ui.combo_com_parity.currentText() == 'even':
                parity = serial.PARITY_EVEN
            elif self.ui.combo_com_parity.currentText() == 'mark':
                parity = serial.PARITY_MARK
            elif self.ui.combo_com_parity.currentText() == 'space':
                parity = serial.PARITY_SPACE
            else:
                parity = serial.PARITY_NONE

            # 停止位
            if self.ui.combo_com_stop_bits.currentText() == '1.5':
                stop_bits = serial.STOPBITS_ONE_POINT_FIVE
            elif self.ui.combo_com_stop_bits.currentText() == '2':
                stop_bits = serial.STOPBITS_TWO
            else:
                stop_bits = serial.STOPBITS_ONE

            self.my_serial = serial.Serial(
                self.serial_list_info[port_index].device,
                int(baud_rate),
                int(data_bits),
                parity,
                stop_bits,
                timeout=0.1)
            if self.my_serial.is_open:
                self.ui.btn_open_com.setText('关闭串口')
            else:
                self.ui.btn_open_com.setText('打开串口')
            # 创建线程接收
            self.serial_recv_tid = threading.Thread(
                target=self.serila_receive_thread, name='serial_recv')
            self.serial_recv_tid.start()
            self.ui.combo_com_baud_rate.setEditable(True)
            self.ui.combo_com_data_bits.setEditable(True)
            self.ui.combo_com_flow_control.setEditable(True)
            self.ui.combo_com_parity.setEditable(True)
            self.ui.combo_com_stop_bits.setEditable(True)
            self.ui.combo_com_port.setEditable(True)

    @Slot()
    def read_cloud(self):
        # 槽函数，btn_cloud_rd按下后调用
        if self.my_serial.is_open:
            self.my_serial.write(b'$FXDIP,?*4E\r\n')

    @Slot()
    def write_cloud(self):
        # 槽函数，btn_cloud_wr按下后调用
        if self.my_serial.is_open:
            ip = self.ui.edit_cloud_ip.text()
            port = int(self.ui.edit_cloud_port.text())
            if port < 65535 and port > 0:
                self.my_serial.write(
                    bytes(f'$FXDIP,{ip},{port}*4E\r\n', encoding='UTF-8'))
            else:
                self.ui.edit_cloud_ip.setText('0~65535')

    @Slot()
    def read_rtd(self):
        # 槽函数，btn_cloud_rd按下后调用
        if self.my_serial.is_open:
            self.my_serial.write(b'$FXRTD,?*4E\r\n')

    @Slot()
    def write_rtd(self):
        # 槽函数，btn_cloud_wr按下后调用
        if self.my_serial.is_open:
            ip = self.ui.edit_rtd_ip.text()
            port = int(self.ui.edit_rtd_port.text())
            username = self.ui.edit_rtd_username.text()
            password = self.ui.edit_rtd_password.text()
            mount = self.ui.edit_rtd_mount.text()
            if port < 65535 and port > 0:
                self.my_serial.write(
                    bytes(
                        f'$FXRTD,{ip},{port},{username},{password},{mount}*4E\r\n',
                        encoding='UTF-8'))
            else:
                self.ui.edit_cloud_ip.setText('0~65535')

    @Slot()
    def read_agnss(self):
        # 槽函数，btn_cloud_rd按下后调用
        if self.my_serial.is_open:
            self.my_serial.write(b'$FXAGN,?*4E\r\n')

    @Slot()
    def write_agnss(self):
        # 槽函数，btn_cloud_wr按下后调用
        if self.my_serial.is_open:
            ip = self.ui.edit_agnss_ip.text()
            filename = self.ui.edit_agnss_filename.text()
            self.my_serial.write(
                bytes(f'$FXAGN,{ip},{filename}*4E\r\n', encoding='UTF-8'))

    @Slot()
    def read_radar(self):
        # 槽函数，btn_cloud_rd按下后调用
        if self.my_serial.is_open:
            self.my_serial.write(b'$FXRAD,?*4E\r\n')

    @Slot()
    def write_radar(self):
        # 槽函数，btn_cloud_wr按下后调用
        if self.my_serial.is_open:
            speed = self.ui.edit_radar.text()
            self.my_serial.write(
                bytes(f'$FXRAD,{speed}*4E\r\n', encoding='UTF-8'))

    @Slot()
    def read_wakeup(self):
        # 槽函数，btn_cloud_rd按下后调用
        if self.my_serial.is_open:
            self.my_serial.write(b'$FXWAK,?*4E\r\n')

    @Slot()
    def write_wakeup(self):
        # 槽函数，btn_cloud_wr按下后调用
        if self.my_serial.is_open:
            shake = self.ui.edit_wakeup_shake.text()
            time = self.ui.edit_wakeup_time.text()
            self.my_serial.write(
                bytes(f'$FXWAK,{shake},{time}*4E\r\n', encoding='UTF-8'))

    @Slot()
    def read_volume(self):
        # 槽函数，btn_cloud_rd按下后调用
        if self.my_serial.is_open:
            self.my_serial.write(b'$FXVIO,?*4E\r\n')

    @Slot()
    def write_volume(self):
        # 槽函数，btn_cloud_wr按下后调用
        if self.my_serial.is_open:
            volume = self.ui.edit_rtd_ip.text()
            self.my_serial.write(
                bytes(f'$FXVIO,{volume}*4E\r\n', encoding='UTF-8'))

    @Slot()
    def read_run_time(self):
        # 槽函数，btn_cloud_rd按下后调用
        if self.my_serial.is_open:
            self.my_serial.write(b'$FXTIM,?*4E\r\n')

    @Slot()
    def write_run_time(self):
        # 槽函数，btn_cloud_wr按下后调用
        if self.my_serial.is_open:
            run_time = self.ui.edit_run_time.text()
            self.my_serial.write(
                bytes(f'$FXTIM,{run_time}*4E\r\n', encoding='UTF-8'))

    @Slot()
    def read_dev_id(self):
        # 槽函数，btn_cloud_rd按下后调用
        if self.my_serial.is_open:
            self.my_serial.write(b'$FXUID,?*4E\r\n')

    @Slot()
    def write_dev_id(self):
        # 槽函数，btn_cloud_wr按下后调用
        if self.my_serial.is_open:
            dev_id = self.ui.edit_dev_id.text()
            self.my_serial.write(
                bytes(f'$FXUID,{dev_id}*4E\r\n', encoding='UTF-8'))

    def cloud_param(self, recv_str):
        # 云服务器参数设置
        head = recv_str.find('$FXDIP,')
        star = recv_str.find('*')
        if head < star:
            if recv_str.find('OK', head, star) >= 0:
                print('recv_str')
            elif recv_str.find('ERROR', head, star) >= 0:
                print('recv_str')
            elif recv_str.count(',', head, star) == 2:
                first_dot = recv_str.find(',', head, star)
                if first_dot >= 0:
                    second_dot = recv_str.find(',', first_dot + 1, star)
                    if second_dot >= 0:
                        self.ui.edit_cloud_ip.setText(recv_str[first_dot +
                                                               1:second_dot])
                        self.ui.edit_cloud_port.setText(recv_str[second_dot +
                                                                 1:star])

    def agnss_param(self, recv_str):
        # 云服务器参数设置
        head = recv_str.find('$FXAGN,')
        star = recv_str.find('*')
        if head < star:
            if recv_str.find('OK', head, star) >= 0:
                print('recv_str')
            elif recv_str.find('ERROR', head, star) >= 0:
                print('recv_str')
            elif recv_str.count(',', head, star) == 2:
                first_dot = recv_str.find(',', head, star)
                if first_dot >= 0:
                    second_dot = recv_str.find(',', first_dot + 1, star)
                    if second_dot >= 0:
                        self.ui.edit_agnss_ip.setText(recv_str[first_dot +
                                                               1:second_dot])
                        self.ui.edit_agnss_filename.setText(
                            recv_str[second_dot + 1:star])

    def rtd_param(self, recv_str):
        # 云服务器参数设置
        head = recv_str.find('$FXRTD,')
        star = recv_str.find('*')
        if head < star:
            if recv_str.find('OK', head, star) >= 0:
                print('recv_str')
            elif recv_str.find('ERROR', head, star) >= 0:
                print('recv_str')
            elif recv_str.count(',', head, star) == 5:
                first_dot = recv_str.find(',', head, star)
                second_dot = recv_str.find(',', first_dot + 1, star)
                three_dot = recv_str.find(',', second_dot + 1, star)
                four_dot = recv_str.find(',', three_dot + 1, star)
                five_dot = recv_str.find(',', four_dot + 1, star)
                self.ui.edit_rtd_ip.setText(recv_str[first_dot + 1:second_dot])
                self.ui.edit_rtd_port.setText(recv_str[second_dot + 1:three_dot])
                self.ui.edit_rtd_username.setText(recv_str[three_dot + 1:four_dot])
                self.ui.edit_rtd_password.setText(recv_str[four_dot + 1:five_dot])
                self.ui.edit_rtd_mount.setText(recv_str[five_dot + 1:star])

    def radar_param(self, recv_str):
        # 云服务器参数设置
        head = recv_str.find('$FXRAD,')
        star = recv_str.find('*')
        if head < star:
            if recv_str.find('OK', head, star) >= 0:
                print('recv_str')
            elif recv_str.find('ERROR', head, star) >= 0:
                print('recv_str')
            elif recv_str.count(',', head, star) == 1:
                first_dot = recv_str.find(',', head, star)
                self.ui.edit_radar.setText(recv_str[first_dot + 1:star])

    def device_param(self, recv_str):
        # 云服务器参数设置
        head = recv_str.find('$FXUID,')
        star = recv_str.find('*')
        if head < star:
            if recv_str.find('OK', head, star) >= 0:
                print('recv_str')
            elif recv_str.find('ERROR', head, star) >= 0:
                print('recv_str')
            elif recv_str.count(',', head, star) == 1:
                first_dot = recv_str.find(',', head, star)
                self.ui.edit_dev_id.setText(recv_str[first_dot + 1:star])

    def volume_param(self, recv_str):
        # 云服务器参数设置
        head = recv_str.find('$FXVOI,')
        star = recv_str.find('*')
        if head < star:
            if recv_str.find('OK', head, star) >= 0:
                print('recv_str')
            elif recv_str.find('ERROR', head, star) >= 0:
                print('recv_str')
            elif recv_str.count(',', head, star) == 1:
                first_dot = recv_str.find(',', head, star)
                self.ui.edit_volume.setText(recv_str[first_dot + 1:star])

    def run_time_param(self, recv_str):
        # 云服务器参数设置
        head = recv_str.find('$FXTIM,')
        star = recv_str.find('*')
        if head < star:
            if recv_str.find('OK', head, star) >= 0:
                print('recv_str')
            elif recv_str.find('ERROR', head, star) >= 0:
                print('recv_str')
            elif recv_str.count(',', head, star) == 1:
                first_dot = recv_str.find(',', head, star)
                self.ui.edit_run_time.setText(recv_str[first_dot + 1:star])

    def wakeup_param(self, recv_str):
        # 云服务器参数设置
        head = recv_str.find('$FXTIM,')
        star = recv_str.find('*')
        if head < star:
            if recv_str.find('OK', head, star) >= 0:
                print('recv_str')
            elif recv_str.find('ERROR', head, star) >= 0:
                print('recv_str')
            elif recv_str.count(',', head, star) == 2:
                first_dot = recv_str.find(',', head, star)
                second_dot = recv_str.find(',', first_dot + 1, star)
                self.ui.edit_wakeup_shake.setText(recv_str[first_dot +
                                                           1:second_dot])
                self.ui.edit_wakeup_time.setText(recv_str[second_dot + 1:star])

    def serila_receive_thread(self):
        # 串口接收
        while self.my_serial.is_open:
            self.rx_bytes = self.my_serial.read(size=65535)
            if len(self.rx_bytes) > 0:
                dollar = self.rx_bytes.find(b'$')
                tail = self.rx_bytes.find(b'\r\n')
                if tail > dollar and tail >= 0 and tail >= 0:
                    recv_str = self.rx_bytes[dollar:tail].decode()
                    self.ui.text_edit_display.append(recv_str)
                    # if recv_str.find('\r\n') >= 0:
                    if recv_str.find('$FXDIP,') >= 0:
                        self.cloud_param(recv_str)
                    elif recv_str.find('$FXAGN,') >= 0:
                        self.agnss_param(recv_str)
                    elif recv_str.find('$FXRTD,') >= 0:
                        self.rtd_param(recv_str)
                    elif recv_str.find('$FXRAD,') >= 0:
                        self.radar_param(recv_str)
                    elif recv_str.find('$FXUID,') >= 0:
                        self.device_param(recv_str)
                    elif recv_str.find('$FXVOI,') >= 0:
                        self.volume_param(recv_str)
                    elif recv_str.find('$FXTIM,') >= 0:
                        self.run_time_param(recv_str)
                    elif recv_str.find('$FXWAK,') >= 0:
                        self.wakeup_param(recv_str)


# class SerilaRxThread(threading.Thread):
#     # 创建一个串口接收线程的类

#     def __init__(self):
#         threading.Thread.__init__(self)

#     def run(self):

if __name__ == "__main__":
    app = QApplication(sys.argv)
    my_widget = MyWidget()
    my_widget.show()
    sys.exit(app.exec())
